/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			ipgsave.h
  \date			Feb 2012
  \author		TNick

  \brief		Contains the definition for IPgSave class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef __IPGSAVE_INC__
#define __IPGSAVE_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<QString>
#include	<QStringList>
#include	<QRgb>
#include	<QMap>
#include	<QColor>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

namespace PgSave		{

/**
	@brief	Interface used to create an abstract way  of saving stuff

	This interface may be used for various purposes, from saving a single
	string of text to saving a complete file.

	The interface only asks a number of methods to be defined and provides
	an outline of the workflow. The classes that actually implement this
	are free to choose how any particular task is performed.

	IPgSave works with paths (nodes). Each element that is saved has a path or is
	part of an array that has a path. Inside, the interface always stores a
	current path that may be altered using setPath(). The path does not have to
	exist prior to the call, as it will be created by this method.

*/
class IPgSave				{

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

#ifdef	PGSAVE_TESTS
	friend void		IPgSave_Tests	( int&, int& );

#ifndef	TEST_OK
#define	TEST_OK		{Outcm = "Ok"; succeded++;}
#define	TEST_FAIL	{Outcm = "Fail"; }
#define	TEST_RESULT( test, message )		\
	if ( test )	TEST_OK	\
		else	TEST_FAIL	\
		qDebug() << QString( message )	\
				 << Outcm;	\
	performed++; b_ok = true;
#endif


#endif


public:

#define	TAG_NAME_TYPE	"type"
#define	TAG_NAME_VALUE	"value"

	/**
	*	@brief	The type of the function used to blind load a setting
	*
	*	The callback is only informed about the path from where the value may
	*	be obtained. The callback is free to do something with that value or
	*	to completly ignore it.
	*
	*	@param	s_path	Where it was found; the path is a "folder" that
	*	contains a type (TAG_NAME_TYPE) and a value (TAG_NAME_VALUE)
	*	@param	kb_data	Data that was provided by the caller that initiated the
	*	load procedure; for us this is an opaque pointer.
	*/
	typedef	bool	(*KB_BLIND_LOAD)	(
			IPgSave *	intf,
			QString		s_path,
			void *		kb_data
			);


	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

protected:


	/**
	*	@brief	list of callbacks for various load types
	*
	*	These callbacks are used when various types when performing blind load
	*/
	QMap<QString, KB_BLIND_LOAD>	kb_load_;


	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:


	/**
	*	@brief	constructor;
	*/
	IPgSave			( void );


	/**
	*	@brief	destructor;
	*/
	virtual				~IPgSave		( void );



	/**
	*	@brief	Add a callback to the list for this instance
	*/
	inline void			appendKb		( QString s_name, KB_BLIND_LOAD new_val)
	{ kb_load_.insert( s_name, new_val ); }


	/**
	*	@brief	removes a callback from the map
	*
	*	@return	true if the key was found, false otherwise
	*/
	inline bool			removeKb		( QString s_name )
	{ return ( kb_load_.remove( s_name ) != 0); }


	/**
	*	@brief	Unites the map with the one that is provided
	*/
	inline void			uniteKb			( QMap<QString, KB_BLIND_LOAD> & other_map)
	{ kb_load_.unite( other_map ); }


	/**
	*	@brief	get the number of callbacks that are registered inside
	*/
	inline int			countKb			( void )
	{ return kb_load_.count(); }


	/**
	*	@brief	get the ncallback associated with a particular string
	*/
	inline KB_BLIND_LOAD	getKb			( QString s_type )
	{ return kb_load_.value( s_type ); }




	/**
	*	@brief	changes the current path in this instance
	*
	*	The path may be changed to an absolute path or provided path
	*	may be appended to current path. If the path starts with a "/" then
	*	the path is absolute, otherwise is relative.
	*
	*	Paths are sepparated by a "/" character despite the opperating system
	*	settings regardng paths.
	*
	*	@param	new_crt	string representing new path
	*/
	virtual bool		setPath			(
			const QString			new_crt
			) = 0;


	/**
	*	@brief	retrieve current path as a list of names sepparated by "/"
	*/
	virtual QString		path			( void ) = 0;


	/**
	*	@brief	retrieve current path as a list of strings
	*
	*	@param	sl_out list where the names are appended; it is not cleared;
	*/
	virtual void		path			( QStringList & sl_out ) = 0;


	/**
	*	@brief	walks up specified number of steps in the path
	*
	*	If the path is already at the root nothing happens. If the number of
	*	steps are larger than the number of steps to the root the root is set.
	*/
	virtual void		cdUp			( unsigned steps = 1 ) = 0;


	/**
	*	@brief	tells if the path exists or not
	*
	*	If the path starts with a "/" then the path is absolute,
	*	otherwise is relative.
	*
	*	The method will return false for paths that are only folders
	*	without holding an actual value.
	*
	*	@param	s_path	string representing the path to test
	*/
	virtual bool		exists			( QString s_path ) = 0;



	/**
	*	@brief	iterates the values in current path
	*
	*	The method uses the callback list to find the proper one to call.
	*	If there is no callback for a particular type the default callback
	*	provided as an argument will be used, except if it is NULL, when they
	*	simply ignored.
	*
	*/
	virtual void		blindLoad		(
			KB_BLIND_LOAD			kb_default = NULL,
			void *					kb_data = NULL
			) = 0;


	/**
	*	@brief	iterates the provided strings and loads the ones it finds
	*
	*	The method uses the callback list to find the proper one to call.
	*	If there is no callback for a particular type the default callback
	*	provided as an argument will be used, except if it is NULL, when they
	*	simply ignored.
	*
	*/
	virtual void		blindLoad		(
			 QStringList			load_list,
			 KB_BLIND_LOAD			kb_default = NULL,
			 void *					kb_data = NULL
			 ) = 0;


	/** @name Retrieving common values
	*
	*/
	//@{

	virtual bool				getBool		(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual qint16				getShort		(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual qint32				getInt		(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual qint64				getLong		(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual qint8				getByte		(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual QColor				getColor	(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual qreal				getDouble	(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual QStringList			getStrLst	(
			QString		s_name,
			bool *		b_ok
			) = 0;

	virtual QString				getStr		(
			QString		s_name,
			bool *		b_ok
			) = 0;

	//@}



	//@{
	//!	change the value of the variable; this is a top level method
	//!
	//!	The methods call the validators if present and informs the callbacks

	virtual bool		set		(
			QString			s_name,
			const qint64	new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const int		new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const bool		new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const char		new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const QRgb		new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const QColor	new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const QString	new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const char *	new_val
			) = 0;

	virtual bool		set		(
			QString			s_name,
			const qreal		new_val
			) = 0;

	//@}


	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class IPgSave	*/

/*  CLASS    =============================================================== */
//
//
//
//

#ifdef	PGSAVE_TESTS
void		IPgSave_Test_i					(
		IPgSave * inst,
		int & performed,
		int & succeded
		);
void		IPgSave_Test_j					(
		IPgSave * inst,
		int & performed,
		int & succeded
		);
void		IPgSave_Tests	( int&, int& );
#endif

}	//	namespace PgSave

#endif // __IPGSAVE_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
